<?php

namespace app\adminapi\service;

use app\adminapi\model\sysfile\SysFileCateDO;
use app\adminapi\model\sysfile\SysFileDO;
use app\common\exception\OtherException;
use think\facade\Env;
use think\facade\Filesystem;

class SysFileService
{
    public static array $ALLOW_TYPE = [1, 2, 3];

    public function list(array $param)
    {
        $where = [];
        if (isset($param['type'])) {
            $where[] = ['type', '=', $param['type']];
        }
        if (isset($param['source'])) {
            $where[] = ['source', '=', $param['source']];
        }
        if (isset($param['name'])) {
            $where[] = ['name', 'like', '%' . $param['name'] . '%'];
        }
        if (isset($param['cid'])) {
            $where[] = ['cid', '=', $param['cid']];
        }
        $paginate['list_rows'] = $param['pageSize'];
        if (isset($param['pageNo'])) {
            $paginate['page'] = $param['pageNo'];
        }
        $result = (new SysFileDO())
            ->where($where)
            ->paginate($paginate)
            ->toArray();
        return [
            'total' => $result['total'],
            'list' => $result['data']
        ];
    }

    public function addSysFile(array $param, $file)
    {
        $this->validTypeIllegal($param['type']);
        $this->validCateExist($param['cid']);
        $this->validFileRealTypeMatched($param['type'], $file->getMime());
        $saveFileInfo = Filesystem::putFile('', $file, 'uniqid');
        $this->validUploadSuccess($saveFileInfo);
        $saveFileDO = [
            'cid' => $param['cid'],
            'type' => $param['type'],
            'source' => 1,
            'name' => $saveFileInfo,
            'uri' => Env::get('project.static_file_prefix') . $saveFileInfo
        ];
        return SysFileDO::create($saveFileDO);
    }

    public function renameSysFile(array $sysFileDO)
    {
        $this->validFileExist($sysFileDO['id']);
        return SysFileDO::update($sysFileDO);
    }

    public function getSysFile(int $id)
    {
        $this->validFileExist($id);
        return SysFileDO::find($id);
    }

    public function moveSysFile(array $fileIds, array $sysFileDO)
    {
        $moveCount = 0;
        foreach ($fileIds as $item) {
            try {
                $this->validFileExist($item);
                $this->validCateExist($sysFileDO['cid']);
                $this->validFileTypeMatched($sysFileDO['cid'], $sysFileDO['type']);
                $update = SysFileDO::update(['id' => $item, 'cid' => $sysFileDO['cid']]);
                if ($update) {
                    $moveCount++;
                }
            } catch (\Exception $e) {
                continue;
            }
        }
        return $moveCount;
    }

    public function deleteSysFile(array $fileIds)
    {
        $deleteCount = 0;
        foreach ($fileIds as $item) {
            try {
                $this->validFileExist($item);
                $relativePath = str_replace(Env::get('project.static_file_prefix'), '', SysFileDO::find($item)->uri);
                $file = Filesystem::disk('local')->has($relativePath);
                $metaData = Filesystem::disk('local')->getMetadata($relativePath);
                if ($file && $metaData['type'] == 'file') {
                    $delete = Filesystem::disk('local')->delete($relativePath);
                    $deleteDb = SysFileDO::destroy($item);
                    if($delete && $deleteDb){
                        $deleteCount++;
                    }
                }
            } catch (\Exception $e) {
                continue;
            }
        }
        return $deleteCount;
    }

    private function validCateExist(int $cid)
    {
        $exist = SysFileCateDO::find($cid);
        if (empty($exist) && $cid !== 0) {
            throw new OtherException("文件分类不存在");
        }
    }

    private function validUploadSuccess($file)
    {
        if (!$file) {
            throw new OtherException("文件上传失败");
        }
    }

    private function validTypeIllegal(int $type)
    {
        if (!in_array($type, self::$ALLOW_TYPE)) {
            throw new OtherException("不合法的文件类型");
        }
    }

    private function validFileRealTypeMatched(int $type, string $fileRealType)
    {
        $realType = from_content_type($fileRealType);
        if ($realType == null) {
            throw new OtherException(sprintf("不支持:%s类型文件", $fileRealType));
        } else {
            if ($type != $realType) {
                throw new OtherException("传入的type与文件实际类型不匹配");
            }
        }
    }

    private function validFileExist(int $id)
    {
        $exist = SysFileDO::find($id);
        if (!$exist) {
            throw new OtherException("文件不存在");
        } else {
            $relativePath = str_replace(Env::get('project.static_file_prefix'), '', $exist->uri);
            if (!Filesystem::disk('local')->has($relativePath)) {
                throw new OtherException("文件已不存在");
            }
        }
    }

    private function validFileTypeMatched(int $cid, int $type)
    {
        $where = [
            ['id', '=', $cid],
            ['type', '=', $type]
        ];
        $exist = SysFileCateDO::where($where)->find();
        if (!$exist) {
            throw new OtherException("不能跨文件类型移动");
        }
    }
}